
/**
  ******************************************************************************
  * Copyright 2021 The grapilot Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       dev_mgr.c
  * @author     baiyang
  * @date       2021-10-20
  ******************************************************************************
  */

/*----------------------------------include-----------------------------------*/
#include <string.h>
#include "dev_mgr.h"
/*-----------------------------------macro------------------------------------*/

/*----------------------------------typedef-----------------------------------*/

/*---------------------------------prototype----------------------------------*/

/*----------------------------------variable----------------------------------*/

/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
/**
  * @brief       
  * @param[in]   name  
  * @param[out]  
  * @retval      
  * @note        
  */
rt_device_t devmgr_get_device(const char *name)
{
    rt_device_t device = NULL;

    device = rt_device_find(name);

    return device;
}

/**
  * @brief       
  * @param[in]   name  
  * @param[out]  
  * @retval      
  * @note        
  */
enum rt_device_class_type devmgr_get_device_type(rt_device_t device)
{
    return device->type;
}

/**
  * @brief       
  * @param[in]   dev  
  * @param[in]   devtype  
  * @param[out]  
  * @retval      
  * @note        
  */
uint32_t devmgr_get_bus_id_devtype(rt_device_t dev, uint8_t devtype)
{
    union DeviceId d = {0};

    if (strcmp(dev->parent.name , ICM20608_SPI_DEVICE_NAME) == 0) {
        d.devid_s.bus_type = dev->type;
        d.devid_s.bus = ICM20608_SPI_BUS_ID;
        d.devid_s.address = ICM20608_SPI_DEVICE_ADDRESS;
        d.devid_s.devtype = devtype;
    }

    if (strcmp(dev->parent.name , MPU9250_SPI_DEVICE_NAME) == 0) {
        d.devid_s.bus_type = dev->type;
        d.devid_s.bus = MPU9250_SPI_BUS_ID;
        d.devid_s.address = MPU9250_SPI_DEVICE_ADDRESS;
        d.devid_s.devtype = devtype;
    }

    if (strcmp(dev->parent.name , MPU60x0_SPI_DEVICE_NAME) == 0) {
        d.devid_s.bus_type = dev->type;
        d.devid_s.bus = MPU60x0_SPI_BUS_ID;
        d.devid_s.address = MPU60x0_SPI_DEVICE_ADDRESS;
        d.devid_s.devtype = devtype;
    }

    if (strcmp(dev->parent.name , L3GD20H_SPI_DEVICE_NAME) == 0) {
        d.devid_s.bus_type = dev->type;
        d.devid_s.bus = L3GD20H_SPI_BUS_ID;
        d.devid_s.address = L3GD20H_SPI_DEVICE_ADDRESS;
        d.devid_s.devtype = devtype;
    }

    if (strcmp(dev->parent.name , MS5611_SPI_DEVICE_NAME) == 0) {
        d.devid_s.bus_type = dev->type;
        d.devid_s.bus = MS5611_SPI_BUS_ID;
        d.devid_s.address = MS5611_SPI_DEVICE_ADDRESS;
        d.devid_s.devtype = devtype;
    }

    if (strcmp(dev->parent.name , LSM9DS0_SPI_DEVICE_NAME) == 0) {
        d.devid_s.bus_type = dev->type;
        d.devid_s.bus = LSM9DS0_SPI_BUS_ID;
        d.devid_s.address = LSM9DS0_SPI_DEVICE_ADDRESS;
        d.devid_s.devtype = devtype;
    }

    return d.devid;
}

/**
  * @brief       
  * @param[in]   dev  
  * @param[in]   devtype  
  * @param[out]  
  * @retval      
  * @note        
  */
bool devmgr_set_speed(rt_device_t dev, enum DeviceSpeed speed)
{
    rt_err_t ret = RT_EOK;
    struct rt_spi_configuration cfg;

    if (dev->type == RT_Device_Class_SPIDevice) {
        if (strcmp(dev->parent.name , ICM20608_SPI_DEVICE_NAME) == 0) {
            cfg.data_width = 8;
            cfg.mode = RT_SPI_MODE_3 | RT_SPI_MSB; /* SPI Compatible Modes 3 */
            cfg.max_hz = (speed == DEV_SPEED_LOW ? ICM20608_SPI_SPEED_LOW : ICM20608_SPI_SPEED_HIGH);
        }

        if (strcmp(dev->parent.name , MPU9250_SPI_DEVICE_NAME) == 0) {
            cfg.data_width = 8;
            cfg.mode = RT_SPI_MODE_3 | RT_SPI_MSB; /* SPI Compatible Modes 3 */
            cfg.max_hz = (speed == DEV_SPEED_LOW ? MPU9250_SPI_SPEED_LOW : MPU9250_SPI_SPEED_HIGH);
        }

        if (strcmp(dev->parent.name , MPU60x0_SPI_DEVICE_NAME) == 0) {
            cfg.data_width = 8;
            cfg.mode = RT_SPI_MODE_3 | RT_SPI_MSB; /* SPI Compatible Modes 3 */
            cfg.max_hz = (speed == DEV_SPEED_LOW ? MPU60x0_SPI_SPEED_LOW : MPU60x0_SPI_SPEED_HIGH);
        }

        if (strcmp(dev->parent.name , L3GD20H_SPI_DEVICE_NAME) == 0) {
            cfg.data_width = 8;
            cfg.mode = RT_SPI_MODE_3 | RT_SPI_MSB; /* SPI Compatible Modes 3 */
            cfg.max_hz = (speed == DEV_SPEED_LOW ? L3GD20H_SPI_SPEED_LOW : L3GD20H_SPI_SPEED_HIGH);
        }

        if (strcmp(dev->parent.name , MS5611_SPI_DEVICE_NAME) == 0) {
            cfg.data_width = 8;
            cfg.mode = RT_SPI_MODE_3 | RT_SPI_MSB; /* SPI Compatible Modes 3 */
            cfg.max_hz = (speed == DEV_SPEED_LOW ? MS5611_SPI_SPEED_LOW : MS5611_SPI_SPEED_HIGH);
        }

        if (strcmp(dev->parent.name , LSM9DS0_SPI_DEVICE_NAME) == 0) {
            cfg.data_width = 8;
            cfg.mode = RT_SPI_MODE_3 | RT_SPI_MSB; /* SPI Compatible Modes 3 */
            cfg.max_hz = (speed == DEV_SPEED_LOW ? LSM9DS0_SPI_SPEED_LOW : LSM9DS0_SPI_SPEED_HIGH);
        }

        struct rt_spi_device* spi_device_t = (struct rt_spi_device*)dev;

        spi_device_t->config.data_width = cfg.data_width;
        spi_device_t->config.mode       = cfg.mode & RT_SPI_MODE_MASK ;
        spi_device_t->config.max_hz     = cfg.max_hz;

        ret = rt_spi_configure(spi_device_t, &cfg);
    }

    return (ret == RT_EOK);
}


/**
 * Wrapper function over #transfer() to read recv_len registers, starting
 * by first_reg, into the array pointed by recv. The read flag passed to
 * #set_read_flag(uint8_t) is ORed with first_reg before performing the
 * transfer.
 *
 * Return: true on a successful transfer, false on failure.
 */
bool devmgr_read_registers(rt_device_t dev, uint8_t first_reg, uint8_t *recv, uint32_t recv_len)
{
    rt_err_t res = RT_ERROR;

    if (dev->type == RT_Device_Class_SPIDevice) {
        res = rt_spi_send_then_recv((struct rt_spi_device*)dev, (void*)&first_reg, 1, (void*)recv, recv_len);
    } else if (dev->type == RT_Device_Class_I2CBUS) {
    
    }

    return (res == RT_EOK);
}

/**
 * Wrapper function over #transfer() to write a byte to the register reg.
 * The transfer is done by sending reg and val in that order.
 *
 * Return: true on a successful transfer, false on failure.
 */
bool devmgr_write_register(rt_device_t dev, uint8_t reg, uint8_t val, bool checked)
{
    bool res = false;
    uint8_t buf[2] = { reg, val };

    if (dev->type == RT_Device_Class_SPIDevice) {
        res = rt_spi_send_then_recv((struct rt_spi_device*)dev, buf, sizeof(buf), NULL, 0);
    } else if (dev->type == RT_Device_Class_I2CBUS) {

    }

    return (res == RT_EOK);
}

/*------------------------------------test------------------------------------*/


